package 微信支付;

import cn.com.haiyunhui.common.core.constant.SecurityConstants;
import cn.com.haiyunhui.common.core.exception.bisWarn.MyBizWarnException;
import cn.com.haiyunhui.common.core.utils.uuid.IdUtils;
import cn.com.haiyunhui.common.core.web.domain.AjaxResult;
import cn.com.haiyunhui.handbusy.domain.*;
import cn.com.haiyunhui.handbusy.domain.business.GasContract;
import cn.com.haiyunhui.handbusy.domain.business.GasOrder;
import cn.com.haiyunhui.handbusy.domain.business.GasWxConfig;
import cn.com.haiyunhui.handbusy.domain.wx.WxPayLog;
import cn.com.haiyunhui.handbusy.mapper.business.GasContractMapper;
import cn.com.haiyunhui.handbusy.mapper.business.GasOrderMapper;
import cn.com.haiyunhui.handbusy.mapper.business.GasWxConfigMapper;
import cn.com.haiyunhui.handbusy.mapper.wx.WxPayLogMapper;
import cn.com.haiyunhui.handbusy.service.PayService;
import cn.com.haiyunhui.handbusy.util.PayUtil;
import cn.com.haiyunhui.handbusy.util.Result;
import cn.com.haiyunhui.handbusy.util.VxPayConfig;
import cn.com.haiyunhui.system.api.RemoteBusinessBaseService;
import cn.com.haiyunhui.system.api.model.CurrencyQuery;
import cn.com.haiyunhui.system.api.model.GasUserAccount;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
@RequestMapping("/pay")
@Slf4j
@GlobalTransactional
public class PayController {

    @Resource
    private PayService payService;

    @Resource
    private RemoteBusinessBaseService businessServiceFeign;


    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Value("${notify.url}")
    private String notify_url;
    //-----------------------

    @Resource
    private WxPayLogMapper wxPayLogMapper;

    @Resource
    private GasOrderMapper gasOrderMapper;
    @Resource
    private GasWxConfigMapper gasWxConfigMapper;
    @Resource
    private GasContractMapper gasContractMapper;


    @PostMapping("notifyTest")
    @ApiOperation("回调测试")
    public Result<?> callBackTest(@RequestParam String outTradeNo) {
        try {
            //根据订单号查微信支付订单
            System.out.println("订单号:" + outTradeNo);
            log.info("判断该订单号是否上锁:" + outTradeNo);
            String dd = (String) redisTemplate.opsForValue().get(outTradeNo);
            if (dd == null) {
                log.info("未上锁，订单号:" + outTradeNo + "，进入销账流程......");
                redisTemplate.opsForValue().set(outTradeNo, "1", 2, TimeUnit.MINUTES);
            } else {
                log.info("已上锁，订单号:" + outTradeNo + "，销账流程正在进行，驳回请求");
                return Result.error("已上锁，订单号:\"+outTradeNo+\"，销账流程正在进行，驳回请求");
            }

            GasOrder pay = gasOrderMapper.selectByPrimaryKey(outTradeNo);
            pay.setOrderNumber(pay.getId());
            System.out.println("订单:" + pay);
            log.info("订单:" + pay);
            if (pay.getState() == 0) {//若状态未支付，走充值缴费流程
                System.out.println(pay);
                try {
                    GasUserAccount account = new GasUserAccount();
                    account.setUserNumber(pay.getUserNumber());
                    account.setEpId(pay.getEpId());
                    account.setOrderNumber(outTradeNo);
                    AjaxResult r = businessServiceFeign.recharge(account, SecurityConstants.FROM_SOURCE);
                    if (!r.isSuccess()) {
                        log.info(r.get("msg").toString());
                        return Result.error(r.get("msg").toString());
                    }
                } catch (Exception e) {
                    log.info("缴费失败，解锁！失败原因：" + e);
                    redisTemplate.delete(outTradeNo);
                    if (e.getMessage().equals("该用户没有查到表具信息")) {
                        return Result.error(e.getMessage() + "请绑定后重新查询订单（补账）");
                    } else {
                        return Result.error(e.getMessage());
                    }
                }
                return Result.ok("缴费成功");
            } else {
                return Result.error("该订单之前已经完成支付流程！");
            }
        } catch (Exception e) {
            return Result.error("数据异常");
        }
    }

    @PostMapping("payWX")
    @ApiOperation("微信支付")
    //必传用户号
    public Result<?> payWX(@RequestBody PayInfoDTO dto, HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        log.info("=========================客户端ip地址{}", ip);
        String userAgent = request.getHeader("user-agent");
        dto.setIp(ip);
        log.info("userAgent = " + userAgent);
        if (userAgent.contains("MicroMessenger") && !userAgent.contains("Windows")) {
            log.info("===========================>进入公众号充值");
            log.info("==================>请求参数:{}", dto);
            return autograph(dto);
        } else if (userAgent.contains("Android") || userAgent.contains("iPhone") || userAgent.contains("iPad")) {
            log.info("===========================>手机端充值");
            log.info("==================>请求参数:{}", dto);
            return pay(dto);
        } else {
            log.info("===========================>PC端充值");
            log.info("==================>请求参数:{}", dto);
            return payNative(dto);
        }
    }

    @PostMapping("pay")
    @ApiOperation("充值缴费下单")
    //必传用户号
    public Result<?> pay(@RequestBody PayInfoDTO dto) {
        System.out.println("进入h5支付方法");
        try {
            ///查询出企业配置信息

            GasWxConfig gasWxConfigDTO = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());

            if (StrUtil.isBlank(gasWxConfigDTO.getMchId())) {
                return Result.error("该公司暂未开通线上支付功能！");
            }
            String url;
            int fee = 0;
            //得到价格，传过来的值*100
            if (null != dto.getAmount()) {
                fee = Integer.parseInt(dto.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.DOWN).toString());
            }
            System.out.println("得到的金额:" + fee);
            //生成订单
            dto.setType(0);
            dto.setPaymentRefundMode(11);
            dto.setPaymentChannel(2);
            String did = null;
            try {
                //调取营收生成订单
                CurrencyQueryDTO queryDTO = new CurrencyQueryDTO();
                BeanUtils.copyProperties(dto, queryDTO);
                //通过epid usernumber 查询到表具id（meterid）需要传入营收服务去判断网表是否注册，并且返回订单id
                GasContract gasCont = gasContractMapper.queryUserNumber(queryDTO);

                String meterId = gasCont.getMeterId();
                queryDTO.setMeterId(meterId);
                //调取营收服务获取订单
                cn.com.haiyunhui.system.api.model.GasUserAccount gasUserAccountDTO = new cn.com.haiyunhui.system.api.model.GasUserAccount();
                BeanUtils.copyProperties(queryDTO, gasUserAccountDTO);
                gasUserAccountDTO.setType(0);
                log.info("调取营收服务获取订单传入参数" + gasUserAccountDTO);
                AjaxResult ajaxResult = businessServiceFeign.generateOrders(gasUserAccountDTO, SecurityConstants.FROM_SOURCE);
                if (ajaxResult.isSuccess()) {
                    did = (String) ajaxResult.get("data");
                }


            } catch (Exception exception) {
                return Result.error("当前用户已销户！");
            }
            //订单号
            System.out.println("得到的订单编号:" + did);

//            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/h5");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("mchid", gasWxConfigDTO.getMchId())
                    .put("appid", gasWxConfigDTO.getAppId())
                    .put("description", "燃气缴费充值")
                    .put("notify_url", notify_url + "/notify/" + dto.getEpId())
                    .put("out_trade_no", did);
            log.info("回调地址:{}", notify_url + "/notify/" + dto.getEpId());
            rootNode.putObject("amount").put("total", fee);
            rootNode.putObject("scene_info").put("payer_client_ip", dto.getIp()).putObject("h5_info").put("type", "Wap");
//            rootNode.putObject("payer")
//                    .put("openid", dto.getOpenId());


            objectMapper.writeValue(bos, rootNode);

            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));

            GasWxConfig gasWxConfigDTO1 = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());
            VxPayConfig v = new VxPayConfig();
            BeanUtils.copyProperties(gasWxConfigDTO1, v);
//            VxPayConfig v = JSONObject.parseObject(dataBaseServiceRemote.queryById(15, 1, 1, dto.getEpId()), VxPayConfig.class);
//            v.setApiV3Key("97bac0f459264f4888473a7cec2abd2c");
//            v.setAppid("wx5343ba9677c55e40");
//            v.setMchSerialNo("7444EA4B20ED833DE5F26422EB7D984697AC00C1");
//            v.setMchId("1615639937");
//            v.setPrivateKeyPath("/mnt/work/cert/1615639937_20221018_cert/apiclient_key.pem");
            CloseableHttpClient httpClient = v.getWxPayClient(v.getVerifier(), v.getPrivateKey());
            CloseableHttpResponse response = httpClient.execute(httpPost);

            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);

            if (bodyAsString.contains("h5_url")) {   //如果接口访问成功就获取url
                JSONObject json = JSONObject.parseObject(bodyAsString);
                url = json.getString("h5_url");
                //再此拼接用户支付完成之后的回跳页面路径
            } else {
//                dataBaseServiceRemote.del(12, 3, did);
//                payService.del(dto.getOrderNumber());
                if (bodyAsString.contains("NO_AUTH")) {
                    JSONObject json = JSONObject.parseObject(bodyAsString);
                    return Result.error("该公司暂未开通H5支付权限！");
                }
                return Result.error("订单生成失败！");
            }


            Map<String, String> payMap = new HashMap<>();
            payMap.put("type", "H5");
            payMap.put("url", url);
            payMap.put("orderNumber", did);
            System.out.println("返回给前端的参数为：" + payMap);
            return Result.ok(payMap);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    @PostMapping("payNative")
    @ApiOperation("Native下单")
    //必传用户号
    public Result<?> payNative(@RequestBody PayInfoDTO dto) {
        System.out.println("进入Native下单");
        try {
            ///查询出企业配置信息
//            GasWxConfig gasWxConfigDTO =
//                    (GasWxConfig)redisTemplate.opsForValue().get("REFUSE_TO_RECEIVE" + dto.getEpId());
//            if (null == gasWxConfigDTO) {
            GasWxConfig gasWxConfigDTO = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());
            //TODO 这里设置时间是因为微信配置添加都是在数据库里面添加的 上面那些方法都还没用起来
//                redisTemplate.opsForValue().set("REFUSE_TO_RECEIVE" + dto.getEpId(),gasWxConfigDTO,90, TimeUnit.DAYS);
//            }
            EnterpriseDTO e = new EnterpriseDTO();
            if (gasWxConfigDTO.getMchId() == null || gasWxConfigDTO.getMchId().equals("")) {
                return Result.error("该公司暂未开通线上支付功能！");
            }
            BeanUtils.copyProperties(gasWxConfigDTO, e);
            ///查询出企业配置信息
//            EnterpriseDTO e =
//                    JSONObject.parseObject(dataBaseServiceRemote.queryById(15, 1, 1, dto.getEpId()), EnterpriseDTO.class);

            String url = "";
            int fee = 0;
            //得到价格，传过来的值*100
            if (null != dto.getAmount()) {
                fee = Integer.parseInt(dto.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.DOWN).toString());
            }
            System.out.println("得到的金额:" + fee);
            //生成订单
            dto.setType(0);
            dto.setPaymentRefundMode(11);
            dto.setPaymentChannel(2);
            String did = null;
            CurrencyQueryDTO queryDTO = new CurrencyQueryDTO();
            BeanUtils.copyProperties(dto, queryDTO);

            GasContract gasCont = gasContractMapper.queryUserNumber(queryDTO);
            String meterId = gasCont.getMeterId();
            queryDTO.setMeterId(meterId);
            //调取营收服务获取订单

            GasUserAccount gasUserAccountDTO = new GasUserAccount();
            BeanUtils.copyProperties(queryDTO, gasUserAccountDTO);

            gasUserAccountDTO.setType(0);
            log.info("调取营收服务获取订单传入参数" + gasUserAccountDTO);
            AjaxResult ajaxResult = businessServiceFeign.generateOrders(gasUserAccountDTO, SecurityConstants.FROM_SOURCE);
            if (ajaxResult.isSuccess()) {
                did = (String) ajaxResult.get("data");
            }
            //订单号
            System.out.println("得到的订单编号:" + did);

//            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("mchid", e.getMchId())
                    .put("appid", e.getAppId())
                    .put("description", "燃气缴费充值")
                    .put("notify_url", notify_url + "/notify/" + dto.getEpId())
                    .put("out_trade_no", did);
            log.info("回调地址:{}", notify_url + "/notify/" + dto.getEpId());
            rootNode.putObject("amount").put("total", fee);
//            rootNode.putObject("scene_info")
//                    .put("payer_client_ip","127.0.0.1")
//                    .putObject("h5_info")
//                    .put("type", "Wap");
//            rootNode.putObject("payer")
//                    .put("openid", dto.getOpenId());

            objectMapper.writeValue(bos, rootNode);

            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            ///查询出企业配置信息
//            GasWxConfig gasWxConfigDTO1 =
//                    (GasWxConfig)redisTemplate.opsForValue().get("REFUSE_TO_RECEIVE" + dto.getEpId());
//            if (null == gasWxConfigDTO1) {
            GasWxConfig gasWxConfigDTO1 = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());
            //TODO 这里设置时间是因为微信配置添加都是在数据库里面添加的 上面那些方法都还没用起来
//                redisTemplate.opsForValue().set("REFUSE_TO_RECEIVE" + dto.getEpId(),gasWxConfigDTO1,90, TimeUnit.DAYS);
//            }
            VxPayConfig v = new VxPayConfig();
            BeanUtils.copyProperties(gasWxConfigDTO1, v);
//            VxPayConfig v = JSONObject.parseObject(dataBaseServiceRemote.queryById(15, 1, 1, dto.getEpId()), VxPayConfig.class);
//            v.setApiV3Key("97bac0f459264f4888473a7cec2abd2c");
//            v.setAppid("wx5343ba9677c55e40");
//            v.setMchSerialNo("7444EA4B20ED833DE5F26422EB7D984697AC00C1");
//            v.setMchId("1615639937");
//            v.setPrivateKeyPath("/mnt/work/cert/1615639937_20221018_cert/apiclient_key.pem");
            CloseableHttpClient httpClient = v.getWxPayClient(v.getVerifier(), v.getPrivateKey());
            CloseableHttpResponse response = httpClient.execute(httpPost);

            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);

            if (bodyAsString.contains("code_url")) {   //如果接口访问成功就获取url
                JSONObject json = JSONObject.parseObject(bodyAsString);
                url = json.getString("code_url");
                //再此拼接用户支付完成之后的回跳页面路径
                Map<String, String> payMap = new HashMap<String, String>();
                payMap.put("type", "Native");
                payMap.put("url", url);
                payMap.put("orderNumber", did);
                System.out.println("返回给前端的参数为：" + payMap);
                return Result.ok(payMap);
            } else {
//                dataBaseServiceRemote.del(12, 3, did);
//                payService.del(dto.getOrderNumber());
                if (bodyAsString.contains("NO_AUTH")) {
                    return Result.error("该公司暂未开通H5支付权限！");
                }
                return Result.error("订单生成失败！");
            }
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    @PostMapping("payApp")
    @ApiOperation("app下单")
    //必传用户号
    public Result<?> payApp(@RequestBody PayInfoDTO dto) {
        System.out.println("进入app下单");
        try {
            ///查询出企业配置信息
            GasWxConfig gasWxConfigDTO = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());
            if (StrUtil.isBlank(gasWxConfigDTO.getMchId())) {
                return Result.error("该公司暂未开通线上支付功能！");
            }
            String url;
            int fee = 0;
            //得到价格，传过来的值*100
            if (null != dto.getAmount()) {
                fee = Integer.parseInt(dto.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.DOWN).toString());
            }
            System.out.println("得到的金额:" + fee);
            //生成订单
            dto.setType(0);
            dto.setPaymentRefundMode(11);
            dto.setPaymentChannel(1);
            String did = "";
            try {
                GasUserAccount gasUserAccount = new GasUserAccount();
                BeanUtils.copyProperties(dto, gasUserAccount);
                gasUserAccount.setType(0);
                AjaxResult ajaxResult = businessServiceFeign.generateOrders(gasUserAccount, SecurityConstants.FROM_SOURCE);
                if (ajaxResult.isSuccess()) {
                    did = (String) ajaxResult.get("data");
                }
            } catch (Exception exception) {
                return Result.error("当前用户已销户！");
            }
            //订单号
            System.out.println("得到的订单编号:" + did);

//            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/app");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("mchid", gasWxConfigDTO.getMchId())
                    .put("appid", gasWxConfigDTO.getAppId())
                    .put("description", "燃气缴费充值")
                    .put("notify_url", notify_url + "/pay/notify/" + dto.getEpId())
                    .put("out_trade_no", did);
            log.info("回调地址:{}", notify_url + "/notify/" + dto.getEpId());
            rootNode.putObject("amount").put("total", fee);
//            rootNode.putObject("scene_info")
//                    .put("payer_client_ip","127.0.0.1")
//                    .putObject("h5_info")
//                    .put("type", "Wap");
//            rootNode.putObject("payer")
//                    .put("openid", dto.getOpenId());

            objectMapper.writeValue(bos, rootNode);

            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
//            GasWxConfig gasWxConfigDTO1 =
//                    (GasWxConfig)redisTemplate.opsForValue().get("REFUSE_TO_RECEIVE" + dto.getEpId());
//            if (null == gasWxConfigDTO1) {
            GasWxConfig gasWxConfigDTO1 = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());
            //TODO 这里设置时间是因为微信配置添加都是在数据库里面添加的 上面那些方法都还没用起来
//                redisTemplate.opsForValue().set("REFUSE_TO_RECEIVE" + dto.getEpId(),gasWxConfigDTO1,90, TimeUnit.DAYS);
//            }
            VxPayConfig v = new VxPayConfig();
            BeanUtils.copyProperties(gasWxConfigDTO1, v);
//            VxPayConfig v = JSONObject.parseObject(dataBaseServiceRemote.queryById(15, 1, 1, dto.getEpId()), VxPayConfig.class);
//            v.setApiV3Key("97bac0f459264f4888473a7cec2abd2c");
//            v.setAppid("wx5343ba9677c55e40");
//            v.setMchSerialNo("7444EA4B20ED833DE5F26422EB7D984697AC00C1");
//            v.setMchId("1615639937");
//            v.setPrivateKeyPath("/mnt/work/cert/1615639937_20221018_cert/apiclient_key.pem");
            CloseableHttpClient httpClient = v.getWxPayClient(v.getVerifier(), v.getPrivateKey());
            CloseableHttpResponse response = httpClient.execute(httpPost);

            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);

            if (bodyAsString.contains("prepay_id")) {   //如果接口访问成功就获取url
                JSONObject json = JSONObject.parseObject(bodyAsString);
                url = json.getString("prepay_id");
                //再此拼接用户支付完成之后的回跳页面路径
                //再此拼接用户支付完成之后的回跳页面路径
                AutographDTO a = new AutographDTO();
                a.setNonceStr(PayUtil.generateNonceStr());
                a.setTimeStamp(PayUtil.getCurrentTimestamp());
                a.setOrderNumber(did);
                a.setAppId(gasWxConfigDTO.getAppId());
                a.setPartnerId(gasWxConfigDTO.getMchId());
                a.setRemarks("Sign=WXPay");
                a.setPartnerId(url);

                String paySign = null;
                String signatureStr = Stream.of(a.getAppId(), String.valueOf(a.getTimeStamp()), a.getNonceStr(), url).collect(Collectors.joining("\n", "", "\n"));
                try {
                    paySign = PayUtil.getSign(signatureStr, v.getPrivateKeyPath());
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

                a.setPaySign(paySign);
                return Result.ok(a);
            } else {
                return Result.error("订单生成失败！");
            }


        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    @PostMapping("queryOrder")
    @ApiOperation("查询订单")
    public Result<?> queryOrder(@RequestParam("orderNumber") String orderNumber, @RequestParam("epId") String epId) {

        System.out.println("进入订单查询方法");
        String tradeState = null;
        //根据订单号查微信支付订单
        GasOrder gasOrder = gasOrderMapper.selectByPrimaryKey(orderNumber);
        PayInfoDTO pay = new PayInfoDTO();
        BeanUtils.copyProperties(gasOrder, pay);
//        PayInfoDTO pay = JSONObject.parseObject(dataBaseServiceRemote.queryById(16,1,2,orderNumber), PayInfoDTO.class);
        if (pay.getState() == 1) {
            return Result.error("之前已经充值成功了！");
        } else {
            try {
                //根据epId获取企业信息
                ///查询出企业配置信息
//                GasWxConfig gasWxConfigDTO =
//                        (GasWxConfig)redisTemplate.opsForValue().get("REFUSE_TO_RECEIVE" + epId);
//                if (null == gasWxConfigDTO) {
                GasWxConfig gasWxConfigDTO = gasWxConfigMapper.selectByPrimaryKey(epId);
                //TODO 这里设置时间是因为微信配置添加都是在数据库里面添加的 上面那些方法都还没用起来
//                    redisTemplate.opsForValue().set("REFUSE_TO_RECEIVE" + epId,gasWxConfigDTO,90, TimeUnit.DAYS);
//                }
                EnterpriseDTO e = new EnterpriseDTO();
                BeanUtils.copyProperties(gasWxConfigDTO, e);
//                EnterpriseDTO e =
//                        JSONObject.parseObject(dataBaseServiceRemote.queryById(15, 1, 1, epId), EnterpriseDTO.class);

                //订单编号
                System.out.println("得到的订单编号:" + orderNumber);

                String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + orderNumber + "?mchid=" + e.getMchId();

                URIBuilder uriBuilder = new URIBuilder(url);
                HttpGet httpGet = new HttpGet(uriBuilder.build());
                httpGet.addHeader("Accept", "application/json");
//                GasWxConfig gasWxConfigDTO1 =
//                        (GasWxConfig)redisTemplate.opsForValue().get("REFUSE_TO_RECEIVE" + epId);
//                if (null == gasWxConfigDTO1) {
                GasWxConfig gasWxConfigDTO1 = gasWxConfigMapper.selectByPrimaryKey(epId);
                //TODO 这里设置时间是因为微信配置添加都是在数据库里面添加的 上面那些方法都还没用起来
//                    redisTemplate.opsForValue().set("REFUSE_TO_RECEIVE" + epId,gasWxConfigDTO1,90, TimeUnit.DAYS);
//                }
                VxPayConfig v = new VxPayConfig();
                BeanUtils.copyProperties(gasWxConfigDTO1, v);
//                VxPayConfig v = JSONObject.parseObject(dataBaseServiceRemote.queryById(15, 1, 1, epId), VxPayConfig.class);
                CloseableHttpClient httpClient = v.getWxPayClient(v.getVerifier(), v.getPrivateKey());
                CloseableHttpResponse response = httpClient.execute(httpGet);

                String bodyAsString = EntityUtils.toString(response.getEntity());
                System.out.println(bodyAsString);

                JSONObject json = JSONObject.parseObject(bodyAsString);

                tradeState = json.getString("trade_state");
                if ("SUCCESS".equals(tradeState)) {
                    log.info("====787用户已经支付=======");
                    Result r = null;
                    r = callBackTest(orderNumber);
                    if (r.getCode() == 200) {
                        r.setMessage("该微信订单支付成功，并且充值成功该,订单号为" + orderNumber);
                    } else {
                        r.setMessage("支付成功，但充值失败，失败信息为" + r.getMessage() + "该订单号为" + orderNumber);
                    }
                    return r;
                } else if ("REFUND".equals(tradeState)) {
                    log.info("该微信订单已退款该订单号为" + orderNumber);
                    return Result.error("该微信订单已退款该订单号为" + orderNumber);

                } else if ("NOTPAY".equals(tradeState)) {
                    log.info("该微信订单未支付该订单号为" + orderNumber);
                    return Result.error("该微信订单未支付该订单号为" + orderNumber);

                } else if ("CLOSED".equals(tradeState)) {
                    log.info("该微信订单已关闭该订单号为" + orderNumber);
                    return Result.error("该微信订单已关闭该订单号为" + orderNumber);

                } else if ("REVOKED".equals(tradeState)) {
                    log.info("该微信订单已撤销（仅付款码支付会返回）该订单号为" + orderNumber);
                    return Result.error("该微信订单已撤销（仅付款码支付会返回）该订单号为" + orderNumber);

                } else if ("USERPAYING".equals(tradeState)) {
                    log.info("该微信订单用户支付中（仅付款码支付会返回）该订单号为" + orderNumber);
                    return Result.error("该微信订单用户支付中（仅付款码支付会返回）该订单号为" + orderNumber);

                } else if ("PAYERROR".equals(tradeState)) {
                    log.info("该微信订单支付失败该订单号为" + orderNumber);
                    return Result.error("该微信订单支付失败该订单号为" + orderNumber);
                }
//                System.out.println("返回给前端的参数为：" + json);
//                return Result.ok(json);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Result.ok(tradeState);
    }

    @PostMapping("processingLogs")
    @ApiOperation("处理错误订单")
    public Result<?> processingLogs(@RequestParam("epId") String epId) {
        CurrencyQueryDTO c = new CurrencyQueryDTO();
        c.setEpId(epId);
        List<WxPayLog> list = wxPayLogMapper.query(c);

        for (WxPayLog p : list) {
            Result r = queryOrder(p.getOrderNumber(), epId);
            if (!r.isSuccess()) {
                System.out.println(r.getMessage());
                continue;
            }
            p.setState(1);
            p.setMsg(r.getMessage());
            WxPayLog wxPayLog = new WxPayLog();
            BeanUtils.copyProperties(p, wxPayLog);
            wxPayLogMapper.updateByPrimaryKeySelective(wxPayLog);
        }
        return Result.ok();
    }

    @PostMapping("/autograph")
    @ApiOperation("调起支付签名")
    public Result<?> autograph(@RequestBody PayInfoDTO dto) {
        System.out.println("进入jsapi支付方法");
        try {
            ///查询出企业配置信息

            GasWxConfig e;
            if (null != dto.getTag()) {
                CurrencyQueryDTO currencyQueryDTO = new CurrencyQueryDTO();
                BeanUtils.copyProperties(dto, currencyQueryDTO);
                e = gasWxConfigMapper.queryByTag(currencyQueryDTO);
            } else {
                e = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());
            }
            if (null == e.getAppId()) {
                return Result.error("未获取到微信配置！");
            }
            String url;
            int fee = 0;
            //得到价格，传过来的值*100
            if (null != dto.getAmount()) {
                fee = Integer.parseInt(dto.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.DOWN).toString());
            }
            System.out.println("得到的金额:" + fee);
            //生成订单

            dto.setPaymentRefundMode(11);
            dto.setPaymentChannel(1);
            dto.setType(0);

            String did = null;
            GasUserAccountDTO gasUserAccountDTO = new GasUserAccountDTO();
            BeanUtils.copyProperties(dto, gasUserAccountDTO);
            //生成订单

            GasContract gasCont = gasContractMapper.queryUserNumber(gasUserAccountDTO);
            String meterId = gasCont.getMeterId();
            gasUserAccountDTO.setMeterId(meterId);
            //调取营收服务获取订单
            cn.com.haiyunhui.system.api.model.GasUserAccount gasUserAccount = new GasUserAccount();
            BeanUtils.copyProperties(gasUserAccountDTO, gasUserAccount);
            gasUserAccount.setType(0);
            log.info("调取营收服务获取订单传入参数" + gasUserAccount);
            AjaxResult ajaxResult = businessServiceFeign.generateOrders(gasUserAccount, SecurityConstants.FROM_SOURCE);
            if (ajaxResult.isSuccess()) {
                did = (String) ajaxResult.get("data");
            }

            //订单号
            log.info("得到的订单编号:" + did);
            System.out.println("得到的订单编号:" + did);

            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
//            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/h5");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("mchid", e.getMchId())
                    .put("appid", e.getAppId())
                    .put("description", "燃气缴费充值")
                    .put("notify_url", notify_url + "/notify/" + dto.getEpId())
                    .put("out_trade_no", did);
            log.info("回调地址:{}", notify_url + "/notify/" + dto.getEpId());
            //订单金额 单位是分
            rootNode.putObject("amount").put("total", fee);
//            rootNode.putObject("scene_info")
//                    .put("payer_client_ip","127.0.0.1")
//                        .putObject("h5_info")
//                        .put("type", "Wap");
            //支付者信息
            rootNode.putObject("payer").put("openid", dto.getOpenId());

            System.out.println(rootNode);
            objectMapper.writeValue(bos, rootNode);

            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
//            GasWxConfig gasWxConfigDTO =
//                    (GasWxConfig)redisTemplate.opsForValue().get("REFUSE_TO_RECEIVE" + dto.getEpId());
//            if (null == gasWxConfigDTO) {
            GasWxConfig gasWxConfigDTO = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());
            //TODO 这里设置时间是因为微信配置添加都是在数据库里面添加的 上面那些方法都还没用起来
//                redisTemplate.opsForValue().set("REFUSE_TO_RECEIVE" + dto.getEpId(),gasWxConfigDTO,90, TimeUnit.DAYS);
//            }
            VxPayConfig v = new VxPayConfig();
            BeanUtils.copyProperties(gasWxConfigDTO, v);
//            VxPayConfig v = JSONObject.parseObject(dataBaseServiceRemote.queryById(15, 1, 1, dto.getEpId()), VxPayConfig.class);
//            v.setApiV3Key("97bac0f459264f4888473a7cec2abd2c");
            v.setAppid(e.getAppId());
//            v.setMchSerialNo("7444EA4B20ED833DE5F26422EB7D984697AC00C1");
//            v.setMchId("1615639937");
//            v.setPrivateKeyPath("/mnt/work/cert/1615639937_20221018_cert/apiclient_key.pem");
            CloseableHttpClient httpClient = v.getWxPayClient(v.getVerifier(), v.getPrivateKey());
            CloseableHttpResponse response = httpClient.execute(httpPost);

            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);

            if (bodyAsString.contains("prepay_id")) {   //如果接口访问成功就获取url
                JSONObject json = JSONObject.parseObject(bodyAsString);
                url = json.getString("prepay_id");

                //再此拼接用户支付完成之后的回跳页面路径
                AutographDTO a = new AutographDTO();
                a.setSignType("RSA");
                a.setNonceStr(PayUtil.generateNonceStr());
                a.setTimeStamp(PayUtil.getCurrentTimestamp());
                a.setOrderNumber(did);
                a.setAppId(e.getAppId());
                String prepayId = "prepay_id=" + url;

                String paySign = null;
                String signatureStr = Stream.of(a.getAppId(), String.valueOf(a.getTimeStamp()), a.getNonceStr(), prepayId).collect(Collectors.joining("\n", "", "\n"));
                try {
                    paySign = PayUtil.getSign(signatureStr, v.getPrivateKeyPath());
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

                a.setPaySign(paySign);
                a.setPrepayId(prepayId);
                return Result.ok(a);
            } else {
//                payService.del(dto.getOrderNumber());
                if (bodyAsString.contains("NO_AUTH")) {
                    JSONObject json = JSONObject.parseObject(bodyAsString);
                    return Result.error("该公司暂未开通H5支付权限！");
                }
                return Result.error("微信信息错误，订单生成失败！");
            }

        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }


    @PostMapping("refund")
    @ApiOperation("退款")
    //必传用户号
    public Result<?> refund(@RequestBody PayInfoDTO dto) {
        System.out.println("进入退款");
        try {
            ///查询出企业配置信息
            GasWxConfig gasWxConfigDTO = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());


            if (StrUtil.isBlank(gasWxConfigDTO.getMchId())) return Result.error("该公司暂未开通线上支付功能！");


            int fee = 0;
            //得到价格，传过来的值*100
            if (null != dto.getAmount()) {
                fee = Integer.parseInt(dto.getAmount().multiply(new BigDecimal("100")).setScale(0, RoundingMode.DOWN).toString());
            }
            System.out.println("得到的金额:" + fee);
            //生成订单
            dto.setType(1);
            dto.setPaymentRefundMode(11);
            dto.setPaymentChannel(dto.getSource() == null ? 9 : dto.getSource());
            String did = IdUtils.fastSimpleUUID();


//            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("out_trade_no", dto.getOrderNumber())
//                    .put("notify_url", "https://miswx.maidacloud.com/handbusy/pay/notify/" + dto.getEpId())
                    .put("out_refund_no", did);
            rootNode.putObject("amount").put("total", fee).put("refund", fee).put("currency", "CNY");
//            rootNode.putObject("scene_info")
//                    .put("payer_client_ip","127.0.0.1")
//                    .putObject("h5_info")
//                    .put("type", "Wap");
//            rootNode.putObject("payer")
//                    .put("openid", dto.getOpenId());

            objectMapper.writeValue(bos, rootNode);

            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
//            GasWxConfig gasWxConfigDTO1 =
//                    (GasWxConfig)redisTemplate.opsForValue().get("REFUSE_TO_RECEIVE" + dto.getEpId());
//            if (null == gasWxConfigDTO1) {
            GasWxConfig gasWxConfigDTO1 = gasWxConfigMapper.selectByPrimaryKey(dto.getEpId());

            VxPayConfig v = new VxPayConfig();
            BeanUtils.copyProperties(gasWxConfigDTO1, v);
//            VxPayConfig v = JSONObject.parseObject(dataBaseServiceRemote.queryById(15, 1, 1, dto.getEpId()), VxPayConfig.class);
//            v.setApiV3Key("97bac0f459264f4888473a7cec2abd2c");
//            v.setAppid("wx5343ba9677c55e40");
//            v.setMchSerialNo("7444EA4B20ED833DE5F26422EB7D984697AC00C1");
//            v.setMchId("1615639937");
//            v.setPrivateKeyPath("/mnt/work/cert/1615639937_20221018_cert/apiclient_key.pem");
            CloseableHttpClient httpClient = v.getWxPayClient(v.getVerifier(), v.getPrivateKey());
            CloseableHttpResponse response = httpClient.execute(httpPost);

            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);

            return Result.ok(bodyAsString);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @PostMapping("business")
    public AjaxResult business(@RequestParam("result") String result, @RequestParam("epId") String epId) {
        try {
            JSONObject json = JSONObject.parseObject(result);
            String outTradeNo = json.getString("out_trade_no");//订单号
            log.info("判断该订单号是否上锁:" + outTradeNo);
            String dd = (String) redisTemplate.opsForValue().get(outTradeNo);
            if (dd == null) {
                log.info("未上锁，订单号:" + outTradeNo + "，进入销账流程......");
                redisTemplate.opsForValue().set(outTradeNo, "1", 2, TimeUnit.MINUTES);
            } else {
                log.info("已上锁，订单号:" + outTradeNo + "，销账流程正在进行，驳回请求");
                return AjaxResult.error("已上锁，订单号:" + outTradeNo + "，销账流程正在进行，驳回请求");
            }
            //根据订单号查微信支付订单
            GasOrder gasOrder = gasOrderMapper.selectByPrimaryKey(outTradeNo);

            log.info("通过订单号获取到订单对象:" + gasOrder);
            //若状态未支付，走充值缴费流程
            if (gasOrder.getState() == 0) {
                log.info("========================订单状态未支付，进入缴费流程====================");
                AjaxResult r;
                try {
                    GasUserAccount account = new GasUserAccount();
                    account.setEpId(gasOrder.getEpId());
                    account.setUserNumber(gasOrder.getUserNumber());
                    account.setOrderNumber(gasOrder.getId());
                    //进入支付方法
                    r = businessServiceFeign.recharge(account, SecurityConstants.FROM_SOURCE);
                } catch (Exception e) {
                    log.info("缴费失败，立即解锁！失败原因是" + e.getMessage());
                    redisTemplate.delete(outTradeNo);
                    throw new Exception(e.getMessage());
                }
                if (!r.isSuccess()) {
                    log.info("缴费失败，解锁！失败原因：" + r.get("msg"));
                    redisTemplate.delete(outTradeNo);
                    throw new Exception((String) r.get("msg"));
                }
            }
            log.info("订单号:" + outTradeNo + "，销账流程结束，2分钟后自动解锁");
            WxPayLog wxPayLog = wxPayLogMapper.queryById(outTradeNo);
            if (null != wxPayLog) {
                wxPayLogMapper.updateStateById(outTradeNo);
            }
            // 支付成功：给微信发送我已接收通知的响应
            // 创建响应对象
            return AjaxResult.success();
        } catch (Exception e) {
            JSONObject json = JSONObject.parseObject(result);
            String outTradeNo = json.getString("out_trade_no");
            redisTemplate.delete(outTradeNo);
            log.info("出现异常，错误订单进行持久化保存,订单号:" + outTradeNo);
            WxPayLog p = new WxPayLog();
            //根据id查询微信支付日志记录
            p.setEpId(epId);
            p.setOrderNumber(outTradeNo);
            log.info("封装日志对象:" + p);
            p.setCreationTime(LocalDateTime.now());
            p.setMsg(e.getMessage());
            WxPayLog wxPayLog = wxPayLogMapper.queryById(outTradeNo);
            if (null == wxPayLog) {
                wxPayLogMapper.insertSelective(p);
            } else {
                wxPayLogMapper.updateByPrimaryKey(p);
            }
            throw new MyBizWarnException(e.getMessage());
        }
    }

}
